//
//  MapViewWithGrid.m
//  iD20
//
//  Created by Andrew Spina on 5/18/10.
//  Copyright 2010 STScI. All rights reserved.
//

#import "MapGridView.h"


@implementation MapGridView

@synthesize firstTapLocation;
@synthesize secondTouchPoint;
@synthesize delegate;
@synthesize gridSize;
@synthesize offset;
@synthesize firstReferencePoint;

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Initialization code
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)coder {
	NSLog(@"Init with Coder Called!");
	if (self = [super initWithCoder:coder]) {
		self->gridSize = 30.0;
		self->firstTapLocation = CGPointMake(-1, -1);
		self->offset = CGPointMake(0, 0);
		mode = DragModeNone;
	}
	return self;
}


- (void)drawRect:(CGRect)rect {
	CGContextRef c = UIGraphicsGetCurrentContext();
	CGContextSetLineWidth(c, 1);
	CGContextSetStrokeColorWithColor(c, [UIColor whiteColor].CGColor);
	// Vertical Lines
	for(int i = 0; i < rect.size.width / self.gridSize; i ++){
		CGContextMoveToPoint(c, rect.origin.x + (gridSize * i) + offset.x, rect.origin.y);
		CGContextAddLineToPoint(c, rect.origin.x + (gridSize * i) + offset.x, rect.origin.y + rect.size.height);
	}
	CGContextStrokePath(c);
	// Horizontal Lines
	CGContextSetStrokeColorWithColor(c, [UIColor blackColor].CGColor);
	for(int i = 0; i < rect.size.height / self.gridSize; i ++){
		CGContextMoveToPoint(c, rect.origin.x, rect.origin.y + (gridSize * i) + offset.y);
		CGContextAddLineToPoint(c, rect.origin.x + rect.size.width, rect.origin.y + (gridSize * i) + offset.y);
	}
	CGContextStrokePath(c);
	// Draw a circle at the first tap point.
	if(firstReferencePoint != nil){
		CGContextSetLineWidth(c, 3);
		CGContextSetStrokeColorWithColor(c, [UIColor greenColor].CGColor);
		//CGContextMoveToPoint(c, 0, 0);
		//CGContextAddLineToPoint(c, 30, 30);
		CGContextAddArc(c, gridSize * firstReferencePoint.x + offset.x, gridSize * firstReferencePoint.y + offset.y, 10, 0, 2*3.15, 0);
		CGContextStrokePath(c);
	}
	if(secondTouchPoint != nil){
		CGContextSetLineWidth(c, 3);
		CGContextSetStrokeColorWithColor(c, [UIColor redColor].CGColor);
		//CGContextMoveToPoint(c, 0, 0);
		//CGContextAddLineToPoint(c, 30, 30);
		CGContextAddArc(c, gridSize * secondTouchPoint.x + offset.x, gridSize * secondTouchPoint.y + offset.y, 10, 0, 2*3.15, 0);
		CGContextStrokePath(c);		
	}
	//UIRectFill(CGRectMake(1, 1, self.frame.size.width - 1, self.frame.size.height - 1));
}

//- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
//	NSLog(@"Touches Ended");
//}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
	UITouch *touch = [touches anyObject];
	CGPoint currentPoint = [touch locationInView:self];
	if(self->mode == DragModePointOne){
		[self firstTapDraggedTo: currentPoint];
	} else if (self->mode == DragModePointTwo) {
		[self secondTapDraggedTo: currentPoint];
	}
}

-(void) secondTapDraggedTo: (CGPoint) dragPoint {
	//NSLog(@"Dragging Point 2!");
	CGPoint firstPointLocation = CGPointMake(firstReferencePoint.x * gridSize + offset.x, firstReferencePoint.y * gridSize + offset.y);
	//CGPoint secondPointLocation = CGPointMake(secondTouchPoint.x * gridSize + offset.x, secondTouchPoint.y * gridSize + offset.y);
	int xDistanceBetween1and2 = secondTouchPoint.x - firstReferencePoint.x;
	int yDistanceBetween1and2 = secondTouchPoint.y - firstReferencePoint.y;
	float newGridSize = MAX( (dragPoint.x - firstPointLocation.x)/xDistanceBetween1and2, (dragPoint.y - firstPointLocation.y)/yDistanceBetween1and2 );
	//NSLog(@"Old: %f New: %f", gridSize, newGridSize);
	gridSize = newGridSize;
	offset.x = firstPointLocation.x - (firstReferencePoint.x * gridSize);
	offset.y = firstPointLocation.y - (firstReferencePoint.y * gridSize);
	
	[self minimizeOffset];
	[self setNeedsDisplay];
}

-(void) firstTapDraggedTo: (CGPoint) dragLocation{
	offset = CGPointMake(dragLocation.x - firstTapLocation.x, dragLocation.y - firstTapLocation.y);
	//NSLog(@"New Offset = %f, %f", offset.x, offset.y);
	[self minimizeOffset];
	[self setNeedsDisplay];
}

// When called, this method reduces the offset by shifting the firstTapLocation by integral amounts.
// Doing this during the drag event aids the rendering logic by allowing them to draw fewer lines.
-(void) minimizeOffset {
	NSLog(@"Minimizing offset");
	NSLog(@"Initial Offset: %f, %f initial tap intersection: %@", offset.x, offset.y, firstReferencePoint);
	int X_adjustment = 0;
	int Y_adjustment = 0;
//	int newTapX = firstReferencePoint.x;
//	int newTapY = firstReferencePoint.y;
	if(offset.x > gridSize/2){
		NSLog(@"Moving intersection right one");
		X_adjustment = 1;
		offset.x = offset.x - gridSize;
		firstTapLocation.x = firstTapLocation.x + gridSize;
	}
	if(offset.x < -1 * gridSize/2){
		NSLog(@"Moving intersection left one");
		X_adjustment = - 1;
		offset.x = offset.x + gridSize;
		firstTapLocation.x = firstTapLocation.x - gridSize;
	}
	if(offset.y > gridSize/2){
		NSLog(@"Moving intersection down one");
		Y_adjustment = 1;
		offset.y = offset.y - gridSize;
		firstTapLocation.y = firstTapLocation.y + gridSize;
	}
	if(offset.y < -1 * gridSize/2){
		NSLog(@"Moving intersection up one");
		Y_adjustment = - 1;
		offset.y = offset.y + gridSize;
		firstTapLocation.y = firstTapLocation.y - gridSize;
	}
	if(firstReferencePoint != nil){
		firstReferencePoint = [Point2d createPointAtX:firstReferencePoint.x + X_adjustment andY:firstReferencePoint.y + Y_adjustment];
	}
	if(secondTouchPoint != nil){
		secondTouchPoint = [Point2d createPointAtX:secondTouchPoint.x + X_adjustment andY:secondTouchPoint.y + Y_adjustment];
	}
	NSLog(@"Final Offset: %f, %f final tap intersection: %@", offset.x, offset.y, firstReferencePoint);
}

-(void)touchesBegan: (NSSet *)touches withEvent:(UIEvent *)event {
	//NSLog(@"Got Set: %@ and event %@", touches, event);
	UITouch *touch =  [touches anyObject];
	if([touch tapCount] == 1){
		CGPoint point = [touch locationInView:self];
		firstTapLocation = point;
		if(firstReferencePoint == nil || [firstReferencePoint equalsPoint:[self convertCGPointToIntersectionLocation:point]]){
			[self firstTouchAtPoint: point];
		} else if (secondTouchPoint == nil || [secondTouchPoint equalsPoint:[self convertCGPointToIntersectionLocation:point]]){
			[self secondTouchAtPoint: point];
		} else {
			self->mode = DragModeNone;
		}
	}
}

- (Point2d *) convertCGPointToIntersectionLocation: (CGPoint) point {
	return [Point2d createPointAtX: (int)((point.x / gridSize) +.5) andY:(int)((point.y / gridSize) + .5)];
}

- (void) secondTouchAtPoint: (CGPoint) point {
	secondTouchPoint = [self convertCGPointToIntersectionLocation:point];
	self->mode = DragModePointTwo;
	[self setNeedsDisplay];
}

-(void) firstTouchAtPoint: (CGPoint) point{
	//	NSLog(@"Double Point = %f, %f", ((point.x / gridSize) +.5), ((point.y / gridSize) + .5));
	Point2d *candidatePoint = [self convertCGPointToIntersectionLocation:point];
	//	NSLog(@"Got Touch at point %f, %f near grid %@", point.x, point.y, candidatePoint);
	NSLog(@"Grid Point %@ is now origin", candidatePoint);
	self.firstReferencePoint = candidatePoint;
	self->mode = DragModePointOne;
	[self setNeedsDisplay];
	// This is the first Touch.
}

- (void)dealloc {
    [super dealloc];
}


@end
